/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *	            File : 	main.cpp
 *       Description :  Генерация CRC-таблицы по заданным параметрам
 *
 *						Реализовано на основе материала:
 *						Ross N. Williams - Элементарное руководство по
 *						CRC алгоритмам обнаружения ошибок
 *
 *            Create :  28.02.2013
 *            Author :  Golovchenko Aleksey (lexgolovchenko@gmail.com)
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <unistd.h>
#include <iostream>
#include <fstream>
#include <cstdio>
#include <iomanip>

#include "tablegen.h"

int main(int argc, char **argv)
{
	std::string help_msg =
			"Опции программы:\n"
			"-p -- параметры CRC-полинома, одной строкой чисел -- WIDTH,POLY,INIT,XOROUT,REF\n"
			"        WIDTH -- степень полинома в битах 16 или 32\n"
			"        POLY -- значение полинома\n"
			"        INIT -- начальное значение регистра CRC\n"
			"        XOROUT -- для xor-комбинации с конечным значением CRC\n"
			"        REF -- \"зеркальный\" алгоритм\n"
			"-f -- файл для генерации таблицы\n"
			"-t -- только таблица, без функции\n"
			"-h -- вызов справки\n";

	// Разбор аргументов командной строки
	CRC_param param;
	bool param_not_set = true;
	bool table_only = false;
	std::string filename;
	std::fstream file;

	int ch, res;
	unsigned int buf1, buf2, buf3, buf4, buf5;
	while (-1 != (ch = getopt(argc, argv, "p:f:th"))) {
		switch (ch) {
		case 'p':
			res = std::sscanf(optarg, "%u,%x,%x,%x,%u", &buf1, &buf2, &buf3, &buf4, &buf5);
			if (res != 5) {
				return -1;
			}

			if (buf1 != 16 && buf1 != 32){
				return -1;
			} else {
				param.width = buf1;
			}

			param.poly = buf2;
			param.init = buf3;
			param.xorout = buf4;
			param.refin = (buf5 != 0);
			param.refout = (buf5 != 0);

			param_not_set = false;

			break;
		case 'f':
			filename = std::string(optarg);
			break;
		case 't':
			table_only = true;
			break;
		case 'h':
			std::cout << help_msg << std::endl;
			return 0;
			break;
		}
	}

	if (param_not_set) {
		std::cerr << "Usage : \"" << argv[0] << " -h\" for additional info" << std::endl;
		return -1;
	}

	std::cout << "Параметры CRC:" << std::endl;
	std::cout << param << std::endl;

	CRC_table_generator *tg;
	if (filename.empty()) {
		tg = new CRC_table_generator(param, std::cout, table_only);
	}
	else {
		file.open(filename.c_str(), std::ios::out);
		if (file.fail()) {
			std::cerr << "Can not create output file " << filename << std::endl;
			return -1;
		}
		tg = new CRC_table_generator(param, file, table_only);
	}

	tg->generate_table();
	delete tg;
	file.close();

	return 0;
}
